#include "Printer.h"
#include <iostream>

using namespace std;

Printer::Printer( unsigned int numStudents, 
				  unsigned int numVendingMachines, 
				  unsigned int numCouriers ) : 
myNumStudents(numStudents), 
myNumVendingMachines(numVendingMachines),
myNumCouriers(numCouriers)
{
	// The num_buffer is number of students, vending machine, courier,
	// one parent, one WatCardOffice, one name server, one truck, 
	// one bottling plant
	int num_buffer_size = myNumStudents + 
						  myNumVendingMachines + 
						  myNumCouriers + 5;

	myStateBuffer.resize(num_buffer_size);

	cout << "Parent\tWATOff\tNames\tTruck\tPlant\t";
	for(unsigned int i=0; i<myNumStudents; i++)
	{
		cout << "Stud:" << i << "\t";
	}

	for(unsigned int i=0; i<myNumVendingMachines; i++)
	{
		cout << "Mach:" << i << "\t";
	}

	for(unsigned int i=0; i<myNumCouriers; i++)
	{
		cout << "Cour:" << i << "\t";
	}
	cout << endl;

	for(unsigned int i=0; i<myStateBuffer.size(); i++)
	{
		cout << "******\t";
	}
	cout << endl;
	
	myStudentStartingPos = 5;
	myVMStartingPos = myStudentStartingPos + myNumStudents;
	myCourierStartingPos = myVMStartingPos + myNumVendingMachines;
}

Printer::~Printer()
{
	cout << "***********************" << endl;
}

void Printer::print( Kind kind, char state )
{
	print(kind, 0, state);
}

void Printer::print( Kind kind, char state, int value1 )
{
	print(kind, 0, state, value1);
}

void Printer::print( Kind kind, char state, int value1, int value2 )
{
	print(kind, 0, state, value1, value2);
}

void Printer::print( Kind kind, unsigned int lid, char state )
{
	// get the actual postion in the buffer
	unsigned int buffer_id = getBufferPos(kind, lid);	

	// Sanity check
	if(buffer_id >= myStateBuffer.size()) return;

	// if the state is finish, we want to do something funcky
	if(state == 'F')
	{
		dumpBuffer();
		for(unsigned int i=0; i<myStateBuffer.size(); i++)
		{
			if(i == buffer_id) cout << state << "\t";
			else cout << "...\t";
		}
		cout << endl;
	}
	else
	{
		// if it is not a empty spot, dump out what we have at the moment
		if(myStateBuffer.at(buffer_id).state != '*') dumpBuffer();
		myStateBuffer.at(buffer_id).state = state;
	}
}

void Printer::print( Kind kind, unsigned int lid, char state, int value1 )
{
	// get the actual postion in the buffer
	unsigned int buffer_id = getBufferPos(kind, lid);	

	// Sanity check
	if(buffer_id >= myStateBuffer.size()) return;

	// if it is not a empty spot, dump out what we have at the moment
	if(myStateBuffer.at(buffer_id).state != '*') dumpBuffer();
	myStateBuffer.at(buffer_id).state = state;
	myStateBuffer.at(buffer_id).info1 = value1;
}

void Printer::print( Kind kind, unsigned int lid, char state, 
					 int value1, int value2 )
{
	// get the actual postion in the buffer
	unsigned int buffer_id = getBufferPos(kind, lid);	
	
	// Sanity check
	if(buffer_id >= myStateBuffer.size()) return;
	
	// if it is not a empty spot, dump out what we have at the moment
	if(myStateBuffer.at(buffer_id).state != '*') dumpBuffer();
	myStateBuffer.at(buffer_id).state = state;
	myStateBuffer.at(buffer_id).info1 = value1;
	myStateBuffer.at(buffer_id).info2 = value2;
}

unsigned int Printer::getBufferPos(Kind kind, int lid)
{
	if(kind == Printer::Student) return myStudentStartingPos + lid;
	if(kind == Printer::Vending) return myVMStartingPos + lid;
	if(kind == Printer::Courier) return myCourierStartingPos + lid;

	return (unsigned int)kind;
}


void Printer::dumpBuffer()
{
	for(unsigned int i=0; i<myStateBuffer.size(); i++)
	{
		if(myStateBuffer.at(i).state != '*') 
			cout << myStateBuffer.at(i).state;
		if(myStateBuffer.at(i).info1 >= 0)
			cout << ":" << myStateBuffer.at(i).info1;
		if(myStateBuffer.at(i).info2 >= 0)
			cout << "," << myStateBuffer.at(i).info2;

		cout << "\t";

		myStateBuffer.at(i).reset();
	}

	cout << endl;
}
